home *** CD-ROM | disk | FTP | other *** search
- /* File MSNBTP.C
- * Bootp requestor
- *
- * Copyright (C) 1991, University of Waterloo.
- * Copyright (C) 1985, 1993, Trustees of Columbia University in the
- * City of New York. Permission is granted to any individual or institution
- * to use this software as long as it is not sold for profit. This copyright
- * notice must be retained. This software may not be included in commercial
- * products without written permission of Columbia University.
- *
- * Original version created by Erick Engelke of the University of
- * Waterloo, Waterloo, Ontario, Canada.
- * Adapted and modified for MS-DOS Kermit by Joe R. Doupnik,
- * Utah State University, jrd@cc.usu.edu, jrd@usu.Bitnet.
- *
- * Last edit
- * 22 May 1993 v3.13
- *
- * BOOTP - Boot Protocol, RFCs 951, 1048, and 1395
- *
- * These extensions get called if bootphost is set to an IP address or
- * to 0xffffffff.
- *
- */
-
- #include "msntcp.h"
- #include "msnlib.h"
-
- /*
- * structure for send and receives
- */
- typedef struct bootp {
- byte bp_op; /* packet op code / message type. */
- byte bp_htype; /* hardware address type, 1 = 10 mb ethernet */
- byte bp_hlen; /* hardware address len, eg '6' for 10mb eth */
- byte bp_hops; /* client sets to zero, optionally used by
- gateways in cross-gateway booting. */
- longword bp_xid; /* transaction ID, a random number */
- word bp_secs; /* filled in by client, seconds elapsed since
- client started trying to boot. */
- word bp_spare;
- longword bp_ciaddr; /* client IP address filled in by client */
- /* if known*/
- longword bp_yiaddr; /* 'your' (client) IP address
- filled by server if client doesn't know */
- longword bp_siaddr; /* server IP address returned in bootreply */
- longword bp_giaddr; /* gateway IP address,
- used in optional cross-gateway booting. */
- byte bp_chaddr[16]; /* client hardware address, filled by client */
- byte bp_sname[64]; /* optional server host name, null terminated*/
-
- byte bp_file[128]; /* boot file name, null terminated string
- 'generic' name or null in bootrequest,
- fully qualified directory-path
- name in bootreply. */
- byte bp_vend[ 64]; /* optional vendor-specific area */
- };
-
- /* bootp.bp_op */
- #define BOOTREQUEST 1
- #define BOOTREPLY 2
-
- /* UDP port numbers, server and client */
- #define IPPORT_BOOTPS 67
- #define IPPORT_BOOTPC 68
-
-
- /******** the following is stolen from NCSA which came from CUTCP *********/
- /* I have not implemented these, but someone may wish to in the future so */
- /* I kept them around. */
- /**************************************************************************/
-
- /*
- * "vendor" data permitted for Stanford boot clients.
- */
- struct vend {
- byte v_magic[4]; /* magic number */
- longword v_flags; /* flags/opcodes, etc. */
- byte v_unused[56]; /* currently unused */
- };
-
- #define VM_STANFORD "STAN" /* v_magic for Stanford */
- #define VM_RFC1048 "\x63\x82\x53\x63" /* magic cookie for BOOTP */
- /* high byte listed first */
- /* v_flags values */
- #define VF_PCBOOT 1 /* an IBMPC or Mac wants environment info */
- #define VF_HELP 2 /* help me, I'm not registered */
- #define TAG_BOOTFILE_SIZE 13 /* tag used by vend fields rfc 1048 */
-
- /* global variables */
- longword bootphost = 0xffffffffL; /* broadcast IP */
- word bootptimeout = 30;
- extern longword set_timeout();
- extern word arp_hardware, MAC_len; /* media details from msnpdi.asm */
- extern byte kdomain[]; /* our domain */
- extern byte kbtpserver[]; /* IP of responding Bootp server */
-
- /*
- * dobootpc - Checks global variables bootptimeout, bootphost
- * if no host specified, the broadcast address
- * returns 0 on success and sets ip address
- */
-
- int
- dobootp(void)
- {
- udp_Socket bsock;
- longword sendtimeout, bootptmo;
- word magictimeout, len;
- struct bootp sendbootp; /* outgoing data */
- struct bootp bootp; /* incoming data */
- struct bootp register * sbp, * rbp;
- longword xid;
- byte *p;
- extern byte * hostname;
-
- /* If we are running SLIP or ODI's SLIP_PPP which do not use
- MAC level addresses use zeros for arp_hardware and MAC_len,
- non-standard but perhaps useful to some cisco terminal servers */
-
- sbp = &sendbootp; /* registered addresses */
- rbp = &bootp;
- memset((byte *)sbp, 0, sizeof(struct bootp));
- memset((byte *)rbp, 0, sizeof(struct bootp));
-
- outs("\r\n Requesting a Bootp server ");
- xid = my_ip_addr; /* a unique value coming from the ethernet card */
- my_ip_addr = 0; /* init our IP address to unknown */
-
- if (udp_open(&bsock, IPPORT_BOOTPC, bootphost, IPPORT_BOOTPS) == 0)
- {
- outs("\n\r Unable to find a bootp server");
- return (-1);
- }
-
- bootptmo = set_timeout(bootptimeout);
- magictimeout = (word)((xid & 7) + 7); /* between 7 and 14 seconds */
-
- sbp->bp_op = BOOTREQUEST;
- sbp->bp_htype = (byte)(arp_hardware & 0xff);
- /* Copy into position the Magic Number used by Bootp */
- bcopy(VM_RFC1048, sbp->bp_vend, 4); /* high byte first */
-
- sbp->bp_hlen = MAC_len; /* length of MAC address */
- sbp->bp_xid = xid;
- sbp->bp_secs = htons(1);
- bcopy(eth_addr, sbp->bp_chaddr, MAC_len);
- kbtpserver[0] = 0;
-
- while (1 == 1) {
- sock_fastwrite(&bsock, (byte *)sbp, sizeof(struct bootp));
- sbp->bp_secs += magictimeout; /* for next time */
- sendtimeout = set_timeout(magictimeout += (xid > 5) & 7);
- outs("."); /* progress tics */
- while (chk_timeout(sendtimeout) == 0)
- {
- if (chk_timeout(bootptmo))
- {
- outs(" Timed out, sorry");
- sock_close(&bsock);
- return (-1); /* fail */
- }
-
- if (tcp_tick(&bsock) == 0) /* major network error if UDP fails */
- {
- outs(" Network troubles, quitting");
- sock_close(&bsock); /* quit now, with error */
- return (-1);
- }
-
- if (sock_dataready(&bsock) == 0)
- continue; /* no data */
-
- /* got a response, lets consider it */
- if ((sizeof(struct bootp) > sock_fastread(&bsock, (byte *)rbp,
- sizeof(struct bootp))) || (rbp->bp_xid != sbp->bp_xid))
- {
- bcopy((byte *)rbp, 0, sizeof(struct bootp)); /*clear*/
- continue; /* too small for bootp pkt, not for us */
- }
-
- if (*(long *)rbp->bp_vend != *(long *)sbp->bp_vend)
- continue; /* magic cookies do not match */
-
- my_ip_addr = ntohl(rbp->bp_yiaddr);
- /* RFC1048 compliant BOOTP vendor field */
- p = &rbp->bp_vend[4]; /* Point just after vendor field */
-
- while (*p != 255)
- switch(*p)
- {
- case 0: /* Nop Pad character */
- p++;
- break;
- case 1: /* Subnet Mask */
- sin_mask = ntohl(*(longword *)(&p[2]));
- p += *(p+1) + 2;
- break;
- case 3: /* gateways */
- for (len = 0; len < *(p+1); len += 4)
- arp_add_gateway(NULL,
- ntohl(*(longword*)(&p[2 + len])));
- p += *(p+1) + 2;
- break;
- case 6: /* Domain Name Servers (BIND) */
- for (len = 0; len < *(p+1); len += 4)
- add_server(&last_nameserver,
- MAX_NAMESERVERS, def_nameservers,
- ntohl(*(longword*)(&p[2 + len])));
- p += *(p+1) + 2;
- break;
- #ifndef KERMIT
- case 8: /* cookie server */
- for (len = 0; len < *(p+1); len += 4)
- add_server(&last_cookie, MAX_COOKIES,
- cookie,ntohl(*(longword*)(&p[2+len])));
- p += *(p+1) + 2;
- break;
- #endif /* KERMIT */
- case 12: /* our hostname, hopefully complete */
- bcopyff(p+2, hostname, (int)(p[1] & 0xff));
- hostname[(int)(p[1] & 0xff)] = '\0';
- p += *(p+1) + 2;
- break;
- case 15: /* RFC-1395, Domain Name tag */
- bcopyff(p+2, kdomain, (int)(p[1] & 0xff));
- p += *(p+1) + 2;
- break;
- case 255:
- break;
- case 2: /* Time offset */
- case 4: /* time servers */
- case 5: /* IEN=116 name server */
- case 7: /* log server */
- case 9: /* lpr server */
- case 10: /* impress server */
- case 11: /* rlp server */
- default:
- p += *(p+1) + 2;
- break;
- } /* end of switch */
- ntoa(kbtpserver, ntohl(bsock.hisaddr));
- /* server IP to dotted decimal */
- sock_close(&bsock);
- return (my_ip_addr != 0? 0: -1);
- } /* while (chk_timeout...*/
- } /* while (1 == 1) */
- }
-